/**
 * Created by Ahmed Medhat & Sweelam on 25/1/2015.
 */

    /* Create obj that hold container.
       Set the svg container and make its attributes as default
    */
    var appending_area='#g';
    var Main_Bound_region = {

    body:d3.select("body"),
    id_Main_Bound_region :0,
    id_Group_Bound_region :0,
    svg_width: 800,
    svg_height: 800,
    g_width: 200,
    g_height: 200,

	SVG: function(){
	     var Container = this.body
                        .append("svg")
                        .attr("width", this.svg_width)
                        .attr("height", this.svg_height)
                        .attr("id","svg"+this.id_Main_Bound_region);
                 this.id_Main_Bound_region++;
                return Container;
		 },

        G: function (append) {

            if(append == 'svg')
                append= '#svg'+(this.id_Main_Bound_region-1);
            else if(append == 'g')
                append= '#g'+(this.id_Group_Bound_region-1);
            else
                append= 'body';


            var GContainer = d3.select(append)
                .append("g")
                .attr("width", this.g_width)
                .attr("height", this.g_height)
                .attr("id","g"+this.id_Group_Bound_region);
            this.id_Group_Bound_region++;
            return GContainer;

        }
};

/* The object that holds all geometry primitives */
    var Geo_Primitives = {

		/**
		 *  Description
		 * @ method : Draw_Axis
		 * @ inputs : Minimum Domain , Maximum Domain , Minimum Range , Maximum Range ,(Type) Vertical || Horizontal and Number of Ticks.
		 * @ return : Non
		 * */
        Draw_Axis: function(dmin,dmax,min_range,max_range,type,no_ticks){
            var c;
            var app= '#g'+(Main_Bound_region.id_Group_Bound_region-1);
            if(type=="H" || type=="h") {
                c=d3.scale.linear()
                    .domain([dmin , dmax])
                    .range([min_range,max_range]);
                var axis_coordinate = d3.svg.axis().ticks(no_ticks).orient("bottom").scale(c);

                d3.select(app).append("g").attr("class", "y axis").attr("transform", "translate(20,20)").call(axis_coordinate);


            }
            if(type=="V" || type=="v")
            {
                c=d3.scale.linear()
                    .domain([dmin , dmax])
                    .range([max_range,min_range]);
                var axis_coordinate = d3.svg.axis().ticks(no_ticks).orient("left").scale(c);

                d3.select(app).append("g").attr("class", "y axis").attr("transform", "translate(20,20)").call(axis_coordinate);
            }

        },

        
        /**
         *  Description
		 * @ method : Draw Line
		 * @ inputs : Coordinates, Stroke color and group id.
		 * @ return : Non
		 * */
        DrawLine : function(x1, y1, x2, y2,stroke,stroke_width ,where_append)
        {
            /* Default Var*/
            where_append            =  appending_area+where_append;
            x1           = x1||0;
            y1           = y1||0;
            x2           = x2||0;
            y2           = y2||0;
            stroke       =stroke||"black";
            stroke_width =stroke_width||1;

            /* Shape D3 Drawer*/
            var line = d3.select( where_append).append("line")
                            .attr("x1", x1)
                            .attr("y1", y1)
                            .attr("x2", x2)
                            .attr("y2", y2)
                            .attr("stroke",stroke)
                            .attr("stroke-width",stroke_width);
            return line;
        },
        
        
        /**
         *  Description
		 * @ method : Draw Rectangle
		 * @ inputs : Coordinates, width, height, corners rotate, body color, Stroke color, opcity degree and group id.
		 * @ return : Non
		 * */
        DrawRect: function(x, y, width, height,rx, ry , fill, stroke, stroke_width, fill_opacity, where_append, data)
        {

            /* Default Var*/
            where_append  =  appending_area+where_append;
            x             = x || 0;
            y             = y || 0;
            rx            =rx || 0;
            ry            =ry || 0;
            width         =width || 5;
            height        =height || 5;
            stroke        =stroke || "red";
            stroke_width  =stroke_width || 1
            fill          =fill || "black";
            fill_opacity  =fill_opacity || 1;

            if(data == null){      /* Shape D3 Drawer*/

                var rect = d3.select(where_append).append("rect")
                    .attr("x", x)
                    .attr("y", y)
                    .attr("width", width )
                    .attr("height", height )
                    .attr("fill", fill)
                    .attr("rx",rx)
                    .attr("ry",ry)
                    .attr("stroke",stroke)
                    .attr("stroke-width",stroke_width)
                    .attr("fill-opacity",fill_opacity);
            }
            else{                /* Shape D3 Drawer binding data */

                var rect = d3.select(where_append)
                    .selectAll("rect")
                    .data(data)
                    .enter()// Magic function to serve a placeholder for data element.
                    .append("rect")
                    .attr("x", x)
                    .attr("y", y)
                    .attr("width", width )
                    .attr("height", height )
                    .attr("fill", fill)
                    .attr("rx",rx)
                    .attr("ry",ry)
                    .attr("stroke",stroke)
                    .attr("stroke-width",stroke_width)
                    .attr("fill-opacity",fill_opacity);
            }


            return rect;
        },

        
        /**
         *  Description
		 * @ method : Draw circle
		 * @ inputs : Coordinates, radius, Stroke color, body color and group id.
		 * @ return : Non
		 * */
        DrawCircle: function(cx,cy,r,stroke,stroke_width,fill, fill_opacity, where_append , data)
        {
            /* Default Var*/
            where_append =  appending_area+where_append;
            cx           =cx||0;
            cy           =cy||0;
            r            =r||2;
            stroke       =stroke||"red";
            stroke_width =stroke_width||1
            fill         =fill || "black";

            if(data == null){       /* Shape D3 Drawer*/
                var circle = d3.select(where_append)
                    .append("circle")
                    .attr("cx" ,cx)
                    .attr("cy" ,cy)
                    .attr("r" ,r)
                    .attr("stroke",stroke)
                    .attr("stroke-width",stroke_width)
                    .attr("fill",fill)
                    .attr("fill-opacity",fill_opacity);

            }
            else{
                              /* Shape D3 Drawer binding data */
                var circle = d3.select(where_append)
                    .selectAll("circle")
                    .data(data)
                    .enter()// Magic function to serve a placeholder for data element.
                    .append("circle")
                    .attr("cx" ,cx)
                    .attr("cy" ,cy)
                    .attr("r" ,r)
                    .attr("stroke",stroke)
                    .attr("stroke-width",stroke_width)
                    .attr("fill",fill)
                    .attr("fill-opacity",fill_opacity);
            }

            return circle;
        },
        
        /**
         *  Description
		 * @ method : Draw Ellipse
		 * @ inputs : Coordinates, radiuses, Stroke color, body color and group id.
		 * @ retuen : Non
		 * */
        DrawEllipse: function(cx, cy, rx, ry,fill,where_append, data)
        {
            /* Default Var*/
            where_append            =  appending_area+where_append;
            cx           =cx||0;
            cy           =cy||0;
            rx            =ry||100;
            ry            =ry||10;
            fill         =fill || "black";

            if(data == null){
                /* Shape D3 Drawer*/
                var ellipse = d3.select(where_append)
                    .append("ellipse")
                    .attr("cx", cx)
                    .attr("cy", cy)
                    .attr("rx", rx)
                    .attr("ry", ry)
                    .attr("fill", fill);
            }
            else{           /* Shape D3 Drawer binding data*/
                var ellipse = d3.select(where_append)
                    .selectAll("ellipse")
                    .data(data)
                    .enter()
                    .append("ellipse")
                    .attr("cx", cx)
                    .attr("cy", cy)
                    .attr("rx", rx)
                    .attr("ry", ry)
                    .attr("fill", fill);
            }

            return ellipse;
        },

      
        /**
         *  Description
		 * @ method : Draw Polygon
		 * @ inputs : Array of Points , Body Color , Stroke Color , Stroke Width ,(Fill Rule) evenodd || nonzero and group id.
		 * @ return : Non
		 * */
        DrawPolygon: function(points,fill,stroke,stroke_width,fill_rule,where_append, data)
        {

            /* Default Var*/
            where_append            =  appending_area+where_append;
            points           =points||"100,10 40,198 100,10 40,198 100,10 40,198";
            fill         =fill || "black";
            stroke         =stroke || "black";
            stroke_width         =stroke_width || 1;
            fill_rule         =fill_rule || "nonzero";

            if(data == null){   /* Shape D3 Drawer*/
                var polygon= d3.select(where_append).append("polygon")
                    .attr("points",points)
                    .attr("fill",fill)
                    .attr("stroke",stroke)
                    .attr("stroke-width",stroke_width)
                    .attr("fill-rule",fill_rule);
            }
            else{       /* Shape D3 Drawer with data*/
                var polygon= d3.select(where_append)
                    .selectAll("polygon")
                    .data(data)
                    .enter()
                    .append("polygon")
                    .attr("points",points)
                    .attr("fill",fill)
                    .attr("stroke",stroke)
                    .attr("stroke-width",stroke_width)
                    .attr("fill-rule",fill_rule);
            }

            return polygon;
        },

        /**
         *  Description
		 * @ method : Draw_Axis
		 * @ inputs : Array of Points , Body Color , Stroke Color , Stroke Width and group id.
		 * @ return : Non
		 * */
        DrawPolyline: function(points,fill,stroke,stroke_width,where_append)
        {

            /* Default Var*/
            where_append            =  appending_area+where_append;
            points           =points||"100,10 40,198 100,10 40,198 100,10 40,198";
            fill         =fill || "white";
            stroke         =stroke || "black";
            stroke_width         =stroke_width || 1;


            /* Shape D3 Drawer*/
            var polyLine = d3.select(where_append).append("polyline")
                            .attr("points",points)
                            .attr("fill",fill)
                            .attr("stroke",stroke)
                            .attr("stroke-width",stroke_width);
            return polyLine;
        }
};


